package com.uduemc.biso.node.web.api.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.PageInfo;
import com.uduemc.biso.core.utils.JsonResult;
import com.uduemc.biso.node.core.dto.FeignFindInfosBySystemIdAndIds;
import com.uduemc.biso.node.core.entities.SArticle;
import com.uduemc.biso.node.core.entities.SArticleSlug;
import com.uduemc.biso.node.core.entities.SSystem;
import com.uduemc.biso.node.core.entities.custom.Article;
import com.uduemc.biso.node.core.node.extities.ArticleTableData;
import com.uduemc.biso.node.core.utils.FilterResponse;
import com.uduemc.biso.node.web.api.dto.RequestArticleTableDataList;
import com.uduemc.biso.node.web.api.dto.RequestArtilce;
import com.uduemc.biso.node.web.api.dto.RequestSaveSystemItemCustomLink;
import com.uduemc.biso.node.web.api.dto.item.ItemCustomLink;
import com.uduemc.biso.node.web.api.pojo.ResponseCustomLink;
import com.uduemc.biso.node.web.api.service.ArticleService;
import com.uduemc.biso.node.web.api.service.SystemItemCustomLinkService;
import com.uduemc.biso.node.web.api.service.SystemService;
import com.uduemc.biso.node.web.api.service.WebSiteService;
import com.uduemc.biso.node.web.api.service.hostsetup.HSSystemDataNumService;
import io.swagger.annotations.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api/system/article")
@Api(tags = "文章系统管理模块")
public class ArticleController {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private ArticleService articleServiceImpl;

    @Autowired
    private SystemService systemServiceImpl;

    @Autowired
    private WebSiteService webSiteServiceImpl;

    @Autowired
    private SystemItemCustomLinkService systemItemCustomLinkServiceImpl;

    @Autowired
    private HSSystemDataNumService hSSystemDataNumServiceImpl;

    @ApiOperation(value = "文章保存", notes = "通过参数中的 id 判断是增加还是修改，如果id=0新增数据", response = Article.class)
    @PostMapping("/save")
    @ApiResponses({@ApiResponse(code = 200, message = "data 同 /info 返回的结果")})
    public JsonResult save(@Valid @RequestBody RequestArtilce requestArtilce, BindingResult errors)
            throws IOException {
        if (errors.hasErrors()) {
            for (FieldError fieldError : errors.getFieldErrors()) {
                String defaultMessage = fieldError.getDefaultMessage();
                String field = fieldError.getField();
                logger.info("field: " + field + " defaultMessage: " + defaultMessage);
                return JsonResult.messageError(defaultMessage);
            }
        }

        if (requestArtilce.getViewCount().longValue() > 1000000000) {
            return JsonResult.messageError("浏览量数字过大，设值不超过10亿！");
        }

        long systemId = requestArtilce.getSystemId();
        SSystem sSystem = systemServiceImpl.getCurrentInfoById(systemId);
        if (sSystem == null || sSystem.getSystemTypeId() == null) {
            return JsonResult.illegal();
        }

        if (sSystem.getSystemTypeId().longValue() == 2L) {
            // slug 必须要有内容
            if (!StringUtils.hasText(requestArtilce.getSlug())) {
                return JsonResult.illegal();
            }
        }

        long id = requestArtilce.getId();
        if (id < 1) {
            // 新增的情况下判断数据是否超过2000条
            int num = hSSystemDataNumServiceImpl.articleNum();
            int usedNum = hSSystemDataNumServiceImpl.usedArticleNum();
            if (usedNum >= num) {
                return JsonResult.messageError("已使用" + usedNum + "条文章数据，无法添加，请联系管理员！");
            }
        }

        // 验证自定义链接是否已经存在，不为空时进行验证
        ItemCustomLink customLink = requestArtilce.getItemCustomLink();
        if (customLink != null) {
            long itemId = requestArtilce.getId();
            if (itemId < 1) {
                itemId = -1;
            }
            short status = customLink.getStatus();
            if (status != 0) {
                List<String> path = customLink.getPath();
                List<String> collect = path.stream().filter(StrUtil::isNotBlank).collect(Collectors.toList());
                String errorMessage = systemItemCustomLinkServiceImpl.validItemCustomLink(sSystem.getHostId(), sSystem.getSiteId(), systemId, itemId,
                        CollUtil.join(collect, "/"));
                if (StrUtil.isNotBlank(errorMessage)) {
                    return JsonResult.messageError(errorMessage);
                }
            }
        }

        Article data = articleServiceImpl.save(requestArtilce);
        if (data == null) {
            return JsonResult.assistance();
        }
        webSiteServiceImpl.cacheClear(sSystem);
        return JsonResult.messageSuccess("保存成功", FilterResponse.filterRepertoryInfo(data));
    }

    @ApiOperation(value = "文章详细信息", notes = "通过 文章数据ID 获取文章的详细数据信息", response = Article.class)
    @ApiImplicitParams({@ApiImplicitParam(name = "articleId", value = "文章数据ID", required = true)})
    @PostMapping("/info")
    @ApiResponses({@ApiResponse(code = 200, message = "data 中数据列表说明如下\n" + "sArticle 文章基础数据\n" + "sArticle.title 文章标题\n" + "sArticle.author 	作者\n"
            + "sArticle.isTop 是否置顶 0-否\n" + "sArticle.orderNum 排序\n" + "sArticle.releasedAt 发布时间\n" + "repertoryQuote 文章封面图片资源\n" + "fileList[] 文章文件资源\n"
            + "fileList[].hrepertory.originalFilename 文件名\n" + "categoryQuote 分类\n" + "sSeoItem SEO信息\n" + "siteHref 前台相对链接地址\n" + "cateHref 前台相对分类连接地址\n"
            + "customLink 同/item-custom-link获取产品系统内容数据的自定义链接\n")})
    public JsonResult info(@RequestParam("articleId") long articleId) throws IOException {
        if (articleId < 1) {
            return JsonResult.illegal();
        }

        Article data = articleServiceImpl.infoCurrent(articleId);
        if (data == null) {
            return JsonResult.assistance();
        }
        return JsonResult.ok(FilterResponse.filterRepertoryInfo(data));
    }

    @PostMapping("/slug-infos")
    public JsonResult slugInfo(@RequestParam long systemId) throws IOException {
        if (systemId < 1) {
            return JsonResult.illegal();
        }
        SSystem sSystem = systemServiceImpl.getCurrentInfoById(systemId);
        if (sSystem.getSystemTypeId() == null || sSystem.getSystemTypeId().longValue() != 2) {
            return JsonResult.illegal();
        }
        Map<Long, List<SArticleSlug>> slugInfoBySystem = articleServiceImpl.getSlugInfoBySystem(sSystem);
        return JsonResult.ok(slugInfoBySystem);
    }

    @PostMapping("/table-data-list")
    public JsonResult tableDataList(@Valid @RequestBody RequestArticleTableDataList requestArticleTableDataList, BindingResult errors)
            throws IOException {
        if (errors.hasErrors()) {
            for (FieldError fieldError : errors.getFieldErrors()) {
                String defaultMessage = fieldError.getDefaultMessage();
                String field = fieldError.getField();
                logger.info("field: " + field + "defaultMessage: " + defaultMessage);
                return JsonResult.messageError(defaultMessage);
            }
        }
        logger.info(requestArticleTableDataList.toString());
        PageInfo<ArticleTableData> data = articleServiceImpl.getInfosByRequestArticleTableDataList(requestArticleTableDataList);
        return JsonResult.ok(data);
    }

    @PostMapping("/change-show")
    public JsonResult changeShow(@RequestParam long id, @RequestParam short isShow)
            throws IOException, InterruptedException {
        if (id < 1L || isShow > (short) 1) {
            return JsonResult.illegal();
        }
        SArticle sArticle = articleServiceImpl.getCurrentInfoById(id);
        if (sArticle == null) {
            return JsonResult.illegal();
        }
        sArticle.setIsShow(isShow);
        boolean bool = articleServiceImpl.updateBySArticle(sArticle);
        if (!bool) {
            return JsonResult.assistance();
        }
        webSiteServiceImpl.cacheClearSystemId(sArticle.getSystemId());
        return JsonResult.messageSuccess("操作成功", id);
    }

    @PostMapping("/change-istop")
    public JsonResult changeIsTop(@RequestParam long id, @RequestParam short isTop)
            throws IOException, InterruptedException {
        if (id < 1L || isTop > (short) 1) {
            return JsonResult.illegal();
        }
        SArticle sArticle = articleServiceImpl.getCurrentInfoById(id);
        if (sArticle == null) {
            return JsonResult.illegal();
        }
        sArticle.setIsTop(isTop);
        boolean bool = articleServiceImpl.updateBySArticle(sArticle);
        if (!bool) {
            return JsonResult.assistance();
        }
        webSiteServiceImpl.cacheClearSystemId(sArticle.getSystemId());
        return JsonResult.messageSuccess("操作成功", id);
    }

    @ApiOperation(value = "修改文章排序", notes = "通过 ID 修改该文章的 orderNum 字段数据，从而影响排序，默认倒序")
    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "文章ID", required = true),
            @ApiImplicitParam(name = "orderNum", value = "排序号", required = true)})
    @PostMapping("/change-ordernum")
    public JsonResult changeOrderno(@RequestParam long id, @RequestParam int orderNum)
            throws IOException, InterruptedException {
        if (id < 1L) {
            return JsonResult.illegal();
        }
        SArticle sArticle = articleServiceImpl.getCurrentInfoById(id);
        if (sArticle == null) {
            return JsonResult.illegal();
        }
        sArticle.setOrderNum(orderNum);
        boolean bool = articleServiceImpl.updateBySArticle(sArticle);
        if (!bool) {
            return JsonResult.assistance();
        }
        webSiteServiceImpl.cacheClearSystemId(sArticle.getSystemId());
        return JsonResult.messageSuccess("操作成功", id);
    }

    @PostMapping("/deletes")
    public JsonResult deletes(@RequestBody List<Long> ids)
            throws IOException, InterruptedException {
        if (CollectionUtils.isEmpty(ids)) {
            return JsonResult.illegal();
        }
        List<SArticle> listSArticle = new ArrayList<SArticle>();
        long systemId = 0;
        for (Long id : ids) {
            if (id == null || id.longValue() < 1) {
                return JsonResult.illegal();
            }

            SArticle sArticle = articleServiceImpl.getCurrentInfoById(id);
            if (sArticle == null) {
                return JsonResult.illegal();
            }
            if (systemId == 0) {
                systemId = sArticle.getSystemId();
            }
            listSArticle.add(sArticle);
        }
        boolean bool = articleServiceImpl.deletes(listSArticle);
        if (!bool) {
            return JsonResult.assistance();
        }
        webSiteServiceImpl.cacheClearSystemId(systemId);
        return JsonResult.messageSuccess("批量删除成功", listSArticle);
    }

    @PostMapping("/delete")
    public JsonResult delete(@RequestParam long id)
            throws IOException, InterruptedException {
        if (id < 1) {
            return JsonResult.illegal();
        }
        List<SArticle> listSArticle = new ArrayList<SArticle>();
        SArticle sArticle = articleServiceImpl.getCurrentInfoById(id);
        if (sArticle == null) {
            return JsonResult.illegal();
        }
        listSArticle.add(sArticle);
        boolean bool = articleServiceImpl.deletes(listSArticle);
        if (!bool) {
            return JsonResult.assistance();
        }
        long systemId = sArticle.getSystemId();
        webSiteServiceImpl.cacheClearSystemId(systemId);
        return JsonResult.messageSuccess("删除成功", sArticle);
    }

    @PostMapping("/infos-by-system-category-id-and-page-limit")
    public JsonResult infosBySystemCategoryIdAndPageLimit(@RequestParam("systemId") long systemId, @RequestParam("categoryId") long categoryId,
                                                          @RequestParam("name") String name, @RequestParam("page") int page, @RequestParam("limit") int limit)
            throws IOException, InterruptedException {
        PageInfo<Article> data = articleServiceImpl.infosCurrentBySystemCategoryIdAndPageLimit(systemId, categoryId, name, page, limit);
        return JsonResult.ok(FilterResponse.filterRepertoryInfoArticle(data));
    }

    @PostMapping("/total-by-system-category-id")
    public JsonResult totalBySystemCategoryId(@RequestParam("systemId") long systemId, @RequestParam("systemCategoryId") long systemCategoryId)
            throws IOException, InterruptedException {
        int total = articleServiceImpl.totalCurrentBySystemCategoryId(systemId, systemCategoryId);
        return JsonResult.ok(total);
    }

    @PostMapping("/infos-by-system-id-and-ids")
    public JsonResult infosBySystemIdAndIds(@RequestBody FeignFindInfosBySystemIdAndIds feignFindInfosBySystemIdAndIds)
            throws IOException, InterruptedException {
        if (feignFindInfosBySystemIdAndIds.getSystemId() < 1 || CollectionUtils.isEmpty(feignFindInfosBySystemIdAndIds.getIds())) {
            return JsonResult.illegal();
        }
        List<Article> listArticle = articleServiceImpl.infosCurrentBySystemIdAndIds(feignFindInfosBySystemIdAndIds);
        return JsonResult.ok(FilterResponse.filterRepertoryInfoArticle(listArticle));
    }

    @PostMapping("/recycle-table-data-list")
    @ApiOperation(value = "文章系统回收站", notes = "文章系统回收站内的数据列表")
    public JsonResult recycleTableDataList(@Valid @RequestBody RequestArticleTableDataList requestArticleTableDataList, BindingResult errors)
            throws IOException {
        if (errors.hasErrors()) {
            for (FieldError fieldError : errors.getFieldErrors()) {
                String defaultMessage = fieldError.getDefaultMessage();
                String field = fieldError.getField();
                logger.info("field: " + field + "defaultMessage: " + defaultMessage);
                return JsonResult.messageError(defaultMessage);
            }
        }
        logger.info(requestArticleTableDataList.toString());
        PageInfo<ArticleTableData> data = articleServiceImpl.getRecycleInfosByRequestArticleTableDataList(requestArticleTableDataList);
        return JsonResult.ok(data);
    }

    @PostMapping("/reduction-recycle-any")
    @ApiOperation(value = "批量还原", notes = "回收站批量还原已经删除的数据")
    public JsonResult reductionRecycleAny(@RequestBody List<Long> ids)
            throws IOException, InterruptedException {
        if (CollectionUtils.isEmpty(ids)) {
            return JsonResult.illegal();
        }
        List<SArticle> listSArticle = new ArrayList<SArticle>();
        for (Long id : ids) {
            if (id == null || id.longValue() < 1) {
                return JsonResult.illegal();
            }

            SArticle sArticle = articleServiceImpl.getCurrentInfoById(id);
            if (sArticle == null) {
                return JsonResult.illegal();
            }
            listSArticle.add(sArticle);
        }
        boolean bool = articleServiceImpl.reductionRecycle(listSArticle);
        if (!bool) {
            return JsonResult.assistance();
        }
        return JsonResult.messageSuccess("批量还原成功", listSArticle);
    }

    @PostMapping("/reduction-recycle-one")
    @ApiOperation(value = "还原单个", notes = "回收站还原单个已经删除的数据")
    public JsonResult reductionRecycleOne(@RequestParam long id)
            throws IOException, InterruptedException {
        if (id < 1) {
            return JsonResult.illegal();
        }
        List<SArticle> listSArticle = new ArrayList<SArticle>();
        SArticle sArticle = articleServiceImpl.getCurrentInfoById(id);
        if (sArticle == null) {
            return JsonResult.illegal();
        }
        listSArticle.add(sArticle);
        boolean bool = articleServiceImpl.reductionRecycle(listSArticle);
        if (!bool) {
            return JsonResult.assistance();
        }
        return JsonResult.messageSuccess("还原成功", sArticle);
    }

    @PostMapping("/clean-recycle-all")
    @ApiOperation(value = "物理全部清除", notes = "物理清除回收站内所有数据，参入的参数为系统ID，成功后返回的数据也是系统ID")
    public JsonResult cleanRecycleAll(@RequestParam("systemId") long systemId)
            throws IOException, InterruptedException {
        if (systemId < 1) {
            return JsonResult.illegal();
        }

        SSystem system = systemServiceImpl.getCurrentInfoById(systemId);
        if (system == null) {
            return JsonResult.illegal();
        }

        boolean bool = articleServiceImpl.cleanRecycleAll(system);
        if (!bool) {
            return JsonResult.assistance();
        }
        return JsonResult.messageSuccess("清空" + system.getName() + "系统回收站成功", systemId);
    }

    @PostMapping("/clean-recycle-any")
    @ApiOperation(value = "物理批量清除", notes = "物理批量清除后无法恢复")
    public JsonResult cleanRecycleAny(@RequestBody List<Long> ids)
            throws IOException, InterruptedException {
        if (CollectionUtils.isEmpty(ids)) {
            return JsonResult.illegal();
        }
        List<SArticle> listSArticle = new ArrayList<SArticle>();
        for (Long id : ids) {
            if (id == null || id.longValue() < 1) {
                return JsonResult.illegal();
            }

            SArticle sArticle = articleServiceImpl.getCurrentInfoById(id);
            if (sArticle == null) {
                return JsonResult.illegal();
            }
            listSArticle.add(sArticle);
        }

        boolean bool = articleServiceImpl.cleanRecycle(listSArticle);
        if (!bool) {
            return JsonResult.assistance();
        }
        return JsonResult.messageSuccess("批量清除成功", listSArticle);
    }

    @PostMapping("/clean-recycle-one")
    @ApiOperation(value = "物理单个清除", notes = "物理单个清除后无法恢复")
    public JsonResult cleanRecycleOne(@RequestParam long id)
            throws IOException, InterruptedException {
        if (id < 1) {
            return JsonResult.illegal();
        }
        List<SArticle> listSArticle = new ArrayList<SArticle>();
        SArticle sArticle = articleServiceImpl.getCurrentInfoById(id);
        if (sArticle == null) {
            return JsonResult.illegal();
        }
        listSArticle.add(sArticle);
        boolean bool = articleServiceImpl.cleanRecycle(listSArticle);
        if (!bool) {
            return JsonResult.assistance();
        }
        return JsonResult.messageSuccess("清除成功", sArticle);
    }

    @ApiOperation(value = "获取文章系统内容数据的自定义链接", notes = "目前只支持产品、文章系统获取数据的自定义链接！", response = ResponseCustomLink.class)
    @ApiImplicitParams({@ApiImplicitParam(name = "systemId", value = "系统数据ID！", required = true),
            @ApiImplicitParam(name = "itemId", value = "文章系统内容数据的ID！", required = true)})
    @PostMapping("/item-custom-link")
    @ApiResponses({@ApiResponse(code = 200, message = "data 中数据列表说明如下\n" + "systemId 系统数据ID\n" + "itemId 文章系统详情内容数据ID\n" + "status 状态 1-开启 0-关闭\n"
            + "title 	文章系统对应itemId的产品或文章下的title数据\n" + "listHDomain 域名列表\n" + "defaultAccessUrlPath 对应的文章系统详情内容数据默认的访问连接地址，如果系统未挂载页面则显示空\n" + "lanno 站点语言前缀\n"
            + "path 自定义链接\n" + "pathOneGroup 自定义链接二级的情况下，第一级页面或者之前使用已经使用过的数据数组\n" + "suffix 自定义链接的后缀")})
    public JsonResult itemCustomLink(@RequestParam("systemId") long systemId, @RequestParam("itemId") long itemId) throws IOException {
        return systemItemCustomLinkServiceImpl.itemCustomLink(systemId, itemId);
    }

    @ApiOperation(value = "保存文章系统内容数据的链接自定义", notes = "目前只支持产品、文章系统的数据链接自定义！", response = ResponseCustomLink.class)
    @PostMapping("/save-item-custom-link")
    @ApiResponses({@ApiResponse(code = 200, message = "同 /item-custom-link 获取文章系统内容数据的自定义链接 返回的结果！")})
    public JsonResult saveItemCustomLink(@Valid @RequestBody RequestSaveSystemItemCustomLink saveSystemItemCustomLink, BindingResult errors)
            throws IOException {
        if (errors.hasErrors()) {
            for (FieldError fieldError : errors.getFieldErrors()) {
                String defaultMessage = fieldError.getDefaultMessage();
                String field = fieldError.getField();
                logger.info("field: " + field + "defaultMessage: " + defaultMessage);
                return JsonResult.messageError(defaultMessage);
            }
        }
        long systemId = saveSystemItemCustomLink.getSystemId();
        long itemId = saveSystemItemCustomLink.getItemId();
        short status = saveSystemItemCustomLink.getStatus();
        List<String> path = saveSystemItemCustomLink.getPath();

        if (status != 0 && CollUtil.isEmpty(path)) {
            return JsonResult.messageError("path 不能为空！");
        }

        List<String> collect = path.stream().filter(StrUtil::isNotBlank).collect(Collectors.toList());
        if (status != 0 && CollUtil.isEmpty(collect)) {
            return JsonResult.messageError("path 不能为空！");
        }

        return systemItemCustomLinkServiceImpl.saveItemCustomLink(systemId, itemId, status, CollUtil.join(collect, "/"), "");
    }

}
